iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0
自我挑戰組

Linux Kernel 網路巡禮系列 第 7

虛擬檔案系統 VFS (1)

  • 分享至 

  • xImage
  •  

在昨天的內容中,我們了解了 network namespace 與 system call 以及 proc 檔案系統之間的關聯。為了更深入理解 proc 檔案系統,我們首先需要了解 Linux 檔案系統的基礎架構,也就是虛擬檔案系統 (Virtual File System, VFS)。

VFS 是 Linux Kernel 中的一層抽象,透過 system call 和 VFS 的抽象,Linux 隔離了應用程式與實際的檔案系統,使得應用程式能夠以通用的 system call 來操作、讀取和寫入不同底層實現的檔案系統。

https://ithelp.ithome.com.tw/upload/images/20240921/20152703ww65X6Kkwl.png

VFS 系統中,有幾個重要的元素:inodedentryfile

inode 檔案

首先,inode 代表的是一個檔案,並且提供了該檔案的 metadata。

// include/linux/fs.h
struct inode {
	umode_t			i_mode; // 存取權限
	kuid_t			i_uid; // 檔案擁有者
	kgid_t			i_gid; // 檔案擁有群
    ...
	unsigned long		i_ino; // inode id
    ...
	loff_t			i_size; // 檔案大小
	struct timespec64	i_atime; // 存取時間
	struct timespec64	i_mtime; // 修改時間
    ...
} __randomize_layout;

inode 結構中,包含了如存取權限 (i_mode)、檔案擁有者 (i_uid, i_gid)、檔案大小 (i_size)、存取時間 (i_atime)、修改時間 (i_mtime) 等資訊。另一個關鍵欄位是 inode number (i_ino),每個 inode 都有一個唯一的 inode number,在單個檔案系統中是唯一的。

目錄 dentry

接下來是 dentrydentrydirectory entry 的縮寫,代表的是一個目錄或檔案。

// include/linux/dcache.h
struct dentry {
	struct dentry *d_parent;	// 父目錄
	struct qstr d_name;         // 目錄或檔案名稱
	struct inode *d_inode;		// 指向目錄或檔案的 inode
    ...
    struct list_head d_child;	// 子目錄或檔案的清單
    ...
} __randomize_layout;

dentry 中,最重要的欄位之一是 d_name,它表示目錄或檔案的名稱。在 Linux 檔案系統中,所有的檔案和目錄是以樹狀結構展開的,所有檔案都從根目錄 / 開始。透過 d_parent 指標以及 d_child List,我們可以在整個檔案系統中移動。例如,當我們想存取 /var/log/dpkg.log 時,Kernel 會從根目錄的 dentry 開始,逐步經過 varlog,直到找到 dpkg.logdentry

值得注意的是,dentry 只代表路徑而不代表實際的檔案。因此,dentry 結構內的 d_inode 指標會指向實際代表檔案的 inode。另外不論是實際保存資料的檔案或著是子目錄,從系統的角度來看都是檔案,所以都會有inode。

這樣的結構也意味著,可能有多個 dentry 指向相同的 inode。這種情況通常發生在我們使用 ln 指令建立硬連結之後,兩個不同路徑在底層指向同一個檔案。由於檔案權限等屬性保存在 inode 中,修改其中一個檔案的權限會影響到所有指向同一 inode 的路徑。

開啟的檔案 file

// include/linux/fs.h
struct file {
    ...
    struct path		f_path; // path
    struct inode		*f_inode;	// 指向 inode
    ...
};

// include/linux/path.h
struct path {
	struct vfsmount *mnt;
	struct dentry *dentry; // 指向 dentry
} __randomize_layout;

最後一個重要的資料結構是 file。儘管結構名稱為 file,實際上是 inode 代表檔案本身,而 file 代表的是某個 process 已經打開的檔案。當某個 process 透過 open 之類的 system call 開啟一個檔案時,系統會為該 process 建立一個 file 資料結構,並且該結構會保存在該 process 的 task_struct 中。

// include/linux/sched.h
struct task_struct {
    ...
    /* Open file information: */
	struct files_struct		*files;
    ...
}

// include/linux/fdtable.h
struct files_struct {
    ...
    struct file __rcu * fd_array[NR_OPEN_DEFAULT];
}

在 Linux Kernel 中,一個 process 的資訊都會保存在 task_struct 資料結構中,其中 files_struct 用來維護 process 打開的檔案。files_struct 中的 fd_array 陣列用來保存所有打開的檔案。當我們透過 file descriptor 進行檔案操作時,系統會從 fd_array 中取得相應的 file 資料結構,然後對應操作該檔案。

https://ithelp.ithome.com.tw/upload/images/20240921/20152703JLItb69nrZ.png

因此,當我們使用 system call、檔案路徑或檔案描述子來操作檔案系統時,實際上是在操作 inodedentryfile 這些資料結構。

總結

今天我們介紹了 Linux VFS 中幾個重要的資料結構,包括 inodedentryfile。這些結構是 Linux 檔案系統運作的抽象元件。明天,我們將進一步探討這些資料結構是如何在實際操作中被使用的。


上一篇
探討 Linux Network Namespace 與 VFS、Proc 檔案系統之間的關聯 - 引言
下一篇
虛擬檔案系統 VFS (2)
系列文
Linux Kernel 網路巡禮14
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言